/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstdarg>
#include <cstring>
#include <iostream>
#include <securec.h>
#include <sstream>
#include <vector>

#include "bluetooth_host.h"
#include "bluetooth_ble_advertiser.h"
#include "bluetooth_ble_central_manager.h"
#include "bluetooth_gatt_client.h"
#include "ohos_bt_gatt.h"

#ifdef __cplusplus
extern "C" {
#endif

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

using namespace std;

namespace OHOS {
namespace Bluetooth {

static BluetoothHost *g_BluetoothHost = nullptr;
static std::shared_ptr<BleCentralManager> g_BleCentralManager = nullptr;
std::shared_ptr<OHOS::Bluetooth::GattClient> g_GattClient = nullptr;
static std::string g_mac;

//  std::shared_ptr<WifiDevice> ptrWifiDevice = WifiDevice::GetInstance(WIFI_DEVICE_ABILITY_ID);
//  std::shared_ptr<WifiScan> ptrWifiScan = WifiScan::GetInstance(WIFI_SCAN_ABILITY_ID);

const int MAX_ARGS = 16;
const int BAND_2GHZ = 1;
const int BAND_5GHZ = 2;
const int CMD_IDX = 1;
const int ARG_IDX = 2;
const int MIN_WPA_LENGTH = 8;

constexpr long SCAN_REPORT_DELAY_MILLIS = 3 * 1000;
constexpr size_t NOTIFY_DATA_MAX_SIZE = 1024 * 1024;

struct sta_cli_cmd {
    const char *cmd;
    void (*handler)(int argc, const char* argv[]);
    const char *usage;
};

static void Log(const char *fmt, ...)
{
    va_list list;
    va_start(list, fmt);
    (void)vfprintf(stdout, fmt, list);
    va_end(list);
    fflush(stdout);
}

#define Logd(fmt, ...) Log(fmt"\n", ##__VA_ARGS__)

class BluetoothHostObserverWapper : public BluetoothHostObserver {
public:
    void OnStateChanged(const int transport, const int status) override
    {
        Logd("BluetoothHostObserverWapper:OnStateChanged: transport[%d], status[%d]", transport, status);
    };
    void OnDiscoveryStateChanged(int status) override
    {
        Logd("BluetoothHostObserverWapper:OnDiscoveryStateChanged status[%d]", status);
    };
    void OnDiscoveryResult(
        const BluetoothRemoteDevice &device, int rssi, const std::string deviceName, int deviceClass) override
    {
        Logd("BluetoothHostObserverWapper:OnDiscoveryResult: deviceName[%s]", deviceName.c_str());
    }
    void OnPairRequested(const BluetoothRemoteDevice &device) override
    {
        Logd("BluetoothHostObserverWapper:OnPairConfirmed");
    }
    void OnPairConfirmed(const BluetoothRemoteDevice &device, int reqType, int number) override
    {
        Logd("BluetoothHostObserverWapper:OnPairConfirmed");
    }
    void OnScanModeChanged(int mode) override
    {
        Logd("BluetoothHostObserverWapper:OnScanModeChanged");
    };
    void OnDeviceNameChanged(const std::string &deviceName) override
    {
        Logd("BluetoothHostObserverWapper:OnDeviceNameChanged deviceName[%s]", deviceName.c_str());
    }
    void OnDeviceAddrChanged(const std::string &address) override
    {
        Logd("BluetoothHostObserverWapper:OnDeviceAddrChanged address[%s]", address.c_str());
    }
};

class BluetoothRemoteDeviceObserverWapper : public BluetoothRemoteDeviceObserver {
public:
    void OnAclStateChanged(const BluetoothRemoteDevice &device, int state, unsigned int reason) override
    {
        Logd("BluetoothRemoteDeviceObserverWapper:OnAclStateChanged");
    }
    void OnPairStatusChanged(const BluetoothRemoteDevice &device, int status, int cause) override
    {
        Logd("BluetoothRemoteDeviceObserverWapper:OnPairStatusChanged");
    }
    void OnRemoteUuidChanged(const BluetoothRemoteDevice &device, const std::vector<ParcelUuid> &uuids) override
    {
        Logd("BluetoothRemoteDeviceObserverWapper:OnRemoteUuidChanged");
    }
    void OnRemoteNameChanged(const BluetoothRemoteDevice &device, const std::string &deviceName) override
    {
        Logd("BluetoothRemoteDeviceObserverWapper:OnRemoteNameChanged");
    }
    void OnRemoteAliasChanged(const BluetoothRemoteDevice &device, const std::string &alias) override
    {
        Logd("BluetoothRemoteDeviceObserverWapper:OnRemoteAliasChanged");
    }

    void OnRemoteCodChanged(const BluetoothRemoteDevice &device, const BluetoothDeviceClass &cod) override
    {
        Logd("BluetoothRemoteDeviceObserverWapper:OnRemoteCodChanged");
    }

    void OnRemoteBatteryLevelChanged(const BluetoothRemoteDevice &device, int batteryLevel) override
    {
        Logd("BluetoothRemoteDeviceObserverWapper:OnRemoteBatteryLevelChanged");
    }

    void OnReadRemoteRssiEvent(const BluetoothRemoteDevice &device, int rssi, int status) override
    {
        Logd("BluetoothRemoteDeviceObserverWapper:OnReadRemoteRssiEvent");
    }
};
static std::shared_ptr<BluetoothHostObserverWapper> g_hostObserver = nullptr;
static std::shared_ptr<BluetoothRemoteDeviceObserverWapper> g_remoteDeviceObserver = nullptr;

class BleCentralManagerCallbackWapper : public BleCentralManagerCallback {
public:
    void OnScanCallback(const BleScanResult &result) override
    {
        OHOS::Bluetooth::BleScanResult deviceCopy = result;
        std::string name = deviceCopy.GetName();
        BluetoothRemoteDevice remote = deviceCopy.GetPeripheralDevice();
        std::string mac = remote.GetDeviceAddr();
        Logd("BleCentralManagerCallbackWapper:OnScanCallback: name:%s, mac:%s", 
            name.c_str(), mac.c_str());
    }
    void OnFoundOrLostCallback(const BleScanResult &result, uint8_t callbackType) override {
        Logd("BleCentralManagerCallbackWapper:OnFoundOrLostCallback");
    };

    void OnBleBatchScanResultsEvent(const std::vector<BleScanResult> &results) override {
        Logd("BleCentralManagerCallbackWapper:OnBleBatchScanResultsEvent");
    }

    void OnStartOrStopScanEvent(int32_t resultCode, bool isStartScan) override
    {
        Logd("BleCentralManagerCallbackWapper:OnStartOrStopScanEvent: resultCode: %d, isStartScan:%d", resultCode, isStartScan);
    }

    void OnNotifyMsgReportFromLpDevice(const UUID &btUuid, int msgType, const std::vector<uint8_t> &value) override
    {
        Logd("BleCentralManagerCallbackWapper:OnNotifyMsgReportFromLpDevice");
    }
};

static std::shared_ptr<BleCentralManagerCallbackWapper> g_BleCallback = nullptr;

class BleGattClientCallback : public GattClientCallback {
    void OnConnectionStateChanged(int connectionState, int ret)
    {
        Logd("BleGattClientCallback:OnConnectionStateChanged");
    };
    void OnCharacteristicWriteResult(const OHOS::Bluetooth::GattCharacteristic &characteristic, int ret)
    {
        Logd("BleGattClientCallback:OnCharacteristicWriteResult");
    };
    void OnServicesDiscovered(int status)
    {
        Logd("BleGattClientCallback:OnServicesDiscovered");
    };
    void OnSetNotifyCharacteristic(const OHOS::Bluetooth::GattCharacteristic &characteristic, int status)
    {
        Logd("BleGattClientCallback:OnSetNotifyCharacteristic");
    };
    void OnCharacteristicChanged(const OHOS::Bluetooth::GattCharacteristic &characteristic)
    {
        Logd("BleGattClientCallback:OnCharacteristicChanged");
    };
    const std::string &getMac() const
    {
        Logd("BleGattClientCallback:getMac");
        return g_mac;
    };
    void setMac(const std::string &mac)
    {
        Logd("BleGattClientCallback:setMac");
    };
    void OnMtuUpdate(int mtu, int ret)
    {
        Logd("BleGattClientCallback:OnMtuUpdate");
    };
};

static std::shared_ptr<BleGattClientCallback> g_GattCallback = nullptr;
 
static void HelpCommand(const char *command);

static bool GeStrValue(int argc, const char *argv[], std::string prefix, std::string& svalue)
{
    svalue = "";
    Logd("enter GeStrValue argc=%d", argc);
    for (int i = ARG_IDX; i < argc; i++) {
        Logd("GeStrValue argc=%d argv[%s]", i, argv[i]);
        std::string input = argv[i];

        if (input.substr(0, prefix.length()) == prefix) {
            svalue = input.substr(prefix.length());  // 提取 "svalue=" 后面的部分
            Logd("%s: %s\n", prefix.c_str(), svalue.c_str());
        } else {
            Logd("输入格式错误\n");
        }
    }
    if (svalue.length() < 0) {
        HelpCommand(argv[CMD_IDX]);
        return false;
    }
    Logd("GeStrValue = %s", svalue.c_str());
    return true;
}

static bool GetMac(int argc, const char *argv[], std::string& mac)
{
    mac = "";
    Logd("enter GetMac argc=%d", argc);
    for (int i = ARG_IDX; i < argc; i++) {
        Logd("GetMac argc=%d argv[%s]", i, argv[i]);
        std::string input = argv[i];
        std::string prefix = "mac=";

        if (input.substr(0, prefix.length()) == prefix) {
            mac = input.substr(prefix.length());  // 提取 "mac=" 后面的部分
            Logd("MAC地址: %s\n", mac.c_str());
        } else {
            Logd("输入格式错误\n");
        }
    }
    if (mac.length() < 0) {
        HelpCommand(argv[CMD_IDX]);
        return false;
    }
    Logd("GetMac = %s", mac.c_str());
    return true;
}

int RegisterCallbacks()
{
    Logd("enter RegisterCallbacks");
    if (g_BluetoothHost == nullptr) {
        g_BluetoothHost = &BluetoothHost::GetDefaultHost();
    }
    g_hostObserver = std::make_shared<BluetoothHostObserverWapper>();
    g_remoteDeviceObserver = std::make_shared<BluetoothRemoteDeviceObserverWapper>();
    g_BluetoothHost->RegisterObserver(g_hostObserver);
    g_BluetoothHost->RegisterRemoteDeviceObserver(g_remoteDeviceObserver);

    if (g_BleCentralManager == nullptr) {
        g_BleCallback = std::make_shared<BleCentralManagerCallbackWapper>();
        g_BleCentralManager = std::make_shared<BleCentralManager>(g_BleCallback);
    }
    return 0;
}

int DeregisterCallbacks()
{
    Logd("enter DeregisterCallbacks");
    if (g_BluetoothHost == nullptr) {
        g_BluetoothHost = &BluetoothHost::GetDefaultHost();
    }

    g_BluetoothHost->DeregisterObserver(g_hostObserver);
    g_BluetoothHost->DeregisterRemoteDeviceObserver(g_remoteDeviceObserver);
    return 0;
}

static void HandleEnable(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    if (g_BluetoothHost == nullptr) {
        g_BluetoothHost = &BluetoothHost::GetDefaultHost();
    }

    if (g_BluetoothHost->IsBrEnabled()) {
        Logd("br enabled already");
    } else {
        g_BluetoothHost->EnableBt();
        Logd("br enabled");
    }

    if (g_BluetoothHost->IsBleEnabled()) {
        Logd("ble enabled already");
        BluetoothState bstate = g_BluetoothHost->GetBluetoothState();
        Logd("ble enabled already %d", bstate);
    } else {
        g_BluetoothHost->EnableBle();
        Logd("ble enabled");
    }
}

static void HandleDisable(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    if (g_BluetoothHost == nullptr) {
        g_BluetoothHost = &BluetoothHost::GetDefaultHost();
    }

    if (g_BluetoothHost->IsBrEnabled()) {
        Logd("br disable ");
        g_BluetoothHost->DisableBt();
    } else {
        Logd("br not enabled ");
    }

    if (g_BluetoothHost->IsBleEnabled()) {
        Logd("ble disabled");
        g_BluetoothHost->DisableBle();
    } else {
        Logd("ble not enabled");
    }
}

static void HandleBrScan(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    g_BluetoothHost->StartBtDiscovery();
}

static void HandleBrGetLocalName(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    std::string name = g_BluetoothHost->GetLocalName();
    Logd("GetLocalName:%s", name.c_str());
}

static void HandleBrSetLocalName(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    std::string name;
    std::string prefix = "name=";
    GeStrValue(argc, argv, prefix, name);
    int ret = g_BluetoothHost->SetLocalName(name);
    Logd("SetLocalName:%d, %s", ret, name.c_str());
}

static void HandleBrGetRemoteName(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    std::string mac;
    GetMac(argc, argv, mac);
    BluetoothRemoteDevice remoteDevice = g_BluetoothHost->GetRemoteDevice(mac, BT_TRANSPORT_BREDR);
    std::string name = remoteDevice.GetDeviceName();
    Logd("GetRemoteName:%s", name.c_str());
}

static void HandleBrSetRemoteName(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBrGetRemoteBatteryInfo(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBrGetLastConnectTime(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBrPairedDevices(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBrPaireState(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBrProfileState(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBrConfirmPaire(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBrSetPinCode(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBleScan(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    BluetoothState bstate = g_BluetoothHost->GetBluetoothState();
    Logd("GetBluetoothState:%d", bstate);

    bool bres = g_BluetoothHost->EnableBle();
    Logd("EnableBle:%d", bres);

    BleScanSettings settings;
    settings.SetReportDelay(0);
    settings.SetScanMode(static_cast<int32_t>(BleScanMode::OHOS_BLE_SCAN_MODE_LOW_POWER));
    settings.SetPhy(static_cast<int32_t>(1));

    std::vector<BleScanFilter> scanFilters;
    BleScanFilter emptyFilter;
    scanFilters.push_back(emptyFilter);

    int status = g_BleCentralManager->StartScan(settings, scanFilters);
    Logd("ble StartScan:%d", status);
}

static void HandleBrStop(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    g_BluetoothHost->CancelBtDiscovery();
}

static void HandleBleStop(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    g_BleCentralManager->StopScan();
}

static void HandleGattConnect(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
    std::string mac;
    GetMac(argc, argv, mac);
    Logd("GetMac mac:%s", mac.c_str());
    BluetoothRemoteDevice remoteDevice(mac, 1);
    g_GattClient = std::make_shared<GattClient>(remoteDevice);
    g_GattClient->Connect(g_GattCallback, false, BT_TRANSPORT_BLE);
}

static void HandleGattDisconnect(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattGetServices(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattGetDeviceName(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattReadCharactValue(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattWriteCharactValue(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattReadDescripValue(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattWriteDescripValue(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattGetRssi(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattSetMtuSize(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattCreateServer(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattAddServices(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattDelServices(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGattCreateClient(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleBleGetConnectedDevices(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleDisconnect(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGetStatus(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGetConfigList(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  if (ptrWifiDevice != nullptr) {
//      vector<WifiDeviceConfig> configs;
//      bool isCandidate = false;
//      ErrCode ret = ptrWifiDevice->GetDeviceConfigs(configs, isCandidate);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success", __func__);
//          PrintfDeviceConfigs(configs);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleGetScanResults(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  if (ptrWifiScan != nullptr) {
//      vector<WifiScanInfo> result;
//      ErrCode ret = ptrWifiScan->GetScanInfoList(result);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success", __func__);
//          PrintfScanResults(result);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleUpdateConfig(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  int nid;
//  WifiDeviceConfig config;
//  if (!GetDeviceConfig(argc, argv, config) || !GetNetworkId(argc, argv, nid)) {
//      return;
//  }
//  if (ptrWifiDevice != nullptr) {
//      int updatedId;
//      ErrCode ret = ptrWifiDevice->UpdateDeviceConfig(config, updatedId);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success, nid=%d", __func__, updatedId);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleAddConfig(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  WifiDeviceConfig config;
//  if (!GetDeviceConfig(argc, argv, config)) {
//      return;
//  }
//  if (ptrWifiDevice != nullptr) {
//      int nid;
//      bool isCandidate = false;
//      ErrCode ret = ptrWifiDevice->AddDeviceConfig(config, nid, isCandidate);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success, nid=%d", __func__, nid);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleRemoveConfigs(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  if (ptrWifiDevice != nullptr) {
//      ErrCode ret = ptrWifiDevice->RemoveAllDevice();
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success", __func__);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleRemoveConfig(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  int nid;
//  if (!GetNetworkId(argc, argv, nid)) {
//      return;
//  }
//  if (ptrWifiDevice != nullptr) {
//      ErrCode ret = ptrWifiDevice->RemoveDevice(nid);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success, nid=%d", __func__, nid);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleConnectNetwork(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  int nid;
//  if (!GetNetworkId(argc, argv, nid)) {
//      return;
//  }
//  if (ptrWifiDevice != nullptr) {
//      bool isCandidate = false;
//      ErrCode ret = ptrWifiDevice->ConnectToNetwork(nid, isCandidate);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success, nid=%d", __func__, nid);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleConnectDevice(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  WifiDeviceConfig config;
//  if (!GetDeviceConfig(argc, argv, config)) {
//      return;
//  }
//  if (ptrWifiDevice != nullptr) {
//      ErrCode ret = ptrWifiDevice->ConnectToDevice(config);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success", __func__);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleGetWifiState(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  if (ptrWifiDevice != nullptr) {
//      int state;
//      ErrCode ret = ptrWifiDevice->GetWifiState(state);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success, wifi state:%d", __func__, state);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleGetWifiDetailState(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGetCountry(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleSetCountry(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGetSignalLevel(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleGetSupportedFeatures(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleEnableConfig(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleDisableConfig(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleReconnect(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
}

static void HandleReassociate(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  if (ptrWifiDevice != nullptr) {
//      ErrCode ret = ptrWifiDevice->ReAssociate();
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success", __func__);
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}

static void HandleGetDeviceMac(int argc, const char* argv[])
{
    Logd("enter command handler:%s", argv[CMD_IDX]);
//  if (ptrWifiDevice != nullptr) {
//      string mac;
//      ErrCode ret = ptrWifiDevice->GetDeviceMacAddress(mac);
//      if (ret == WIFI_OPT_SUCCESS) {
//          Logd("%s success, mac is %s:", __func__, mac.c_str());
//      } else {
//          Logd("%s failed", __func__);
//      }
//  }
}


static void ParseUserInput(std::string command);
static void HandleInteractive(int argc, const char* argv[])
{
    string inputLine;
    Logd("enter interactive mode! input quit to exit this mode");
    Logd("please input command:");
    RegisterCallbacks();

    do {
        getline(cin, inputLine);
        if (inputLine == "quit") {
            DeregisterCallbacks();
            break;
        } else {
            ParseUserInput(inputLine);
            Logd("please input command:");
        }
    } while (true);
}

static const struct sta_cli_cmd g_sta_cli_cmds[] = {
    {"enable", HandleEnable, "enable"},
    {"disable", HandleDisable, "disable"},
    {"brscan", HandleBrScan, "brscan"},
    {"brstop", HandleBrStop, "brstop"},
    {"getlocname", HandleBrGetLocalName, "getlocname"},
    {"setlocname", HandleBrSetLocalName, "setlocname"},
    {"getretname", HandleBrGetRemoteName, "getretname"},
    {"setretname", HandleBrSetRemoteName, "setretname"},
    {"getrebatinfo", HandleBrGetRemoteBatteryInfo, "getrebatinfo"},
    {"getconntime", HandleBrGetLastConnectTime, "getconntime"},
    {"getpaires", HandleBrPairedDevices, "getpaires"},
    {"getpairestate", HandleBrPaireState, "getpairestate"},
    {"getprofilestate", HandleBrProfileState, "getprofilestate"},
    {"confirmPaire", HandleBrConfirmPaire, "confirmPaire"},
    {"setPinCode", HandleBrSetPinCode, "setPinCode"},

    {"blescan", HandleBleScan, "blescan"},
    {"blestop", HandleBleStop, "blestop"},
    {"gattconn", HandleGattConnect, "bleconn mac=%s"},
    {"gattdisc", HandleGattDisconnect, "bledisc"},
    {"gattgetserv", HandleGattGetServices, "gattgetserv"},
    {"gattgetdname", HandleGattGetDeviceName, "gattgetdname"},
    {"gattreadcv", HandleGattReadCharactValue, "gattreadcv"},
    {"gattwritecv", HandleGattWriteCharactValue, "gattwritecv"},
    {"gattreaddes", HandleGattReadDescripValue, "gattreaddes"},
    {"gattwritedes", HandleGattWriteDescripValue, "gattwritedes"},
    {"gattgetrssi", HandleGattGetRssi, "gattgetrssi"},
    {"gattsetmtu", HandleGattSetMtuSize, "gattsetmtu"},
    {"gattcreateserver", HandleGattCreateServer, "gattcreateserver"},
    {"gattaddservices", HandleGattAddServices, "gattaddservices"},
    {"gattdelservices", HandleGattDelServices, "gattdelservices"},
    {"gattcreateclient", HandleGattCreateClient, "gattcreateclient"},
    {"blegetconnected", HandleBleGetConnectedDevices, "blegetconnected"},

    {"get_status", HandleGetStatus, "get_status"},
    {"get_config_list", HandleGetConfigList, "get_config_list"},
    {"get_scan_results", HandleGetScanResults, "get_scan_results"},
    {"update_config", HandleUpdateConfig, "update_config nid=%d ssid=%s pwd=%s key_mgmt=open/wpa/wpa2"},
    {"add_config", HandleAddConfig, "add_config ssid=%s pwd=%s key_mgmt=open/wpa/wpa2"},
    {"remove_configs", HandleRemoveConfigs, "remove_configs"},
    {"remove_config", HandleRemoveConfig, "remove_config nid=%d"},
    {"connect_network", HandleConnectNetwork, "connect_network nid=%d"},
    {"connect_device", HandleConnectDevice, "connect_device ssid=%s pwd=%s key_mgmt=open/wpa/wpa2"},
    {"get_wifi_state", HandleGetWifiState, "get_wifi_state"},
    {"get_wifi_detail_state", HandleGetWifiDetailState, "get_wifi_detail_state"},
    {"set_country", HandleSetCountry, "set_country code=%s"},
    {"get_country", HandleGetCountry, "get_country"},
    {"get_signal_level", HandleGetSignalLevel, "get_signal_level rssi=%d band=2g/5g"},
    {"get_supported_features", HandleGetSupportedFeatures, "get_supported_features"},
    {"enable_config", HandleEnableConfig, "enable_config nid=%d disableothers=true/false"},
    {"disable_config", HandleDisableConfig, "disable_config nid=%d"},
    {"reconnect", HandleReconnect, "reconnect"},
    {"reassociate", HandleReassociate, "reassociate"},
    {"get_device_mac", HandleGetDeviceMac, "get_device_mac"},
    {"interactive", HandleInteractive, "interactive"}
};

static void HelpCommand(const char *command)
{
    int count = ARRAY_SIZE(g_sta_cli_cmds);
    for (int i = 0; i < count; i++) {
        if (strcmp(command, g_sta_cli_cmds[i].cmd) == 0) {
            Logd("%s", g_sta_cli_cmds[i].usage);
            return;
        }
    }
    Logd("can not find command %s", command);
}

static void Help(void)
{
    Logd("%s", "support command as follows:");
    int count = ARRAY_SIZE(g_sta_cli_cmds);
    for (int i = 0; i < count; i++) {
        Logd("%s", g_sta_cli_cmds[i].usage);
    }
}

static void HandleUserCommand(int argc, const char *argv[])
{
    if (argc < ARG_IDX) {
        Help();
        return;
    }

    int count = ARRAY_SIZE(g_sta_cli_cmds);
    for (int i = 0; i < count; i++) {
        if (strcmp(g_sta_cli_cmds[i].cmd, argv[CMD_IDX]) == 0) {
            if (g_sta_cli_cmds[i].handler != nullptr) {
            // RegisterCallbacks();
            g_sta_cli_cmds[i].handler(argc, argv);
            // DeregisterCallbacks();
            } else {
                Logd("no handler for command:%s", g_sta_cli_cmds[i].cmd);
            }
            return;
        }
    }
    Help();
}

static void ParseUserInput(std::string command)
{
    int argc = 0;
    const char* argv[MAX_ARGS] = { nullptr };
    vector<string> cmdArgs;

    std::istringstream istr(command);
    for (std::string s; istr >> s;) {
        cmdArgs.push_back(s);
    }

    argc = cmdArgs.size() + CMD_IDX;
    if (argc > MAX_ARGS) {
        argc = MAX_ARGS;
    }
    for (int i = CMD_IDX; i < argc; i++) {
        argv[i] = cmdArgs[i - CMD_IDX].c_str();
    }
    HandleUserCommand(argc, argv);
    cmdArgs.clear();
}

}
}
 
 int main(int argc, char *argv[])
 {
     OHOS::Bluetooth::HandleUserCommand(argc, const_cast<const char **>(argv));
     return 0;
 }

 #ifdef __cplusplus
}
#endif
 